﻿using System;
using System.Linq.Expressions;
using System.Reflection;

using Epic.Core;

namespace Epic
{
    [Obsolete("Don't use until fixed.", true)]
    public class BoundMember<T>
        where T : class
    {
#pragma warning disable 1591

        public T Target { get; private set; }
        public MemberInfo Member { get; private set; }

        private void InitializeBoundMember(LambdaExpression expr)
        {
            var memberAccess = expr.Body as MemberExpression;
            if (memberAccess == null)
                throw NewException.Argument(() => expr, Resources.NotMemberAccess);

            //========//========//========//========

            if (memberAccess.Expression is ParameterExpression)
            {
                // does nothing, leaves Target null
            }
            else
            {
                var targetExpr = memberAccess.Expression as ConstantExpression;
                if (targetExpr == null)
                    throw NewException.Argument(() => expr, Resources.InvalidTargetExpression);

                if (targetExpr.Type != typeof(T))
                    throw NewException.Argument(() => expr, Resources.InvalidTargetType);

                if (targetExpr.Value == null)
                    throw NewException.Argument(() => expr, Resources.TargetIsNull);

                Target = (T)targetExpr.Value;
            }

            //========//========//========//========

            Member = memberAccess.Member;
        }

        public BoundMember(Expression<Func<object>> expr)
        {
            InitializeBoundMember(expr);
        }
        public BoundMember(T target, Expression<Func<object>> expr)
        {
            if (target == null)
                throw NewException.ArgumentNull(() => expr, Resources.TargetIsNull);

            InitializeBoundMember(expr);

            if (target != Target)
                throw NewException.Argument(() => expr, Resources.TargetNotMatch);
        }
        public BoundMember(T target, Expression<Func<T, object>> expr)
        {
            if (target == null)
                throw NewException.ArgumentNull(() => expr, Resources.TargetIsNull);

            InitializeBoundMember(expr);

            if (Target == null)
            {
                // set Target to the value of target, for parameterized expression
                Target = target;
            }
            else if (target != Target)
            {
                throw NewException.Argument(() => expr, Resources.TargetNotMatch);
            }
        }
    }
}
